<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
            let data = { 
                name:'atgg',
                address: 'bj'
            }

            //这么写会有问题，一旦读取或设置data.name，就会无限递归导致栈溢出
            /*
            Object.defineProperty(data, 'name', {
                get(){
                    return data.name
                },
                set(val){
                    data.name = val 
                    console.log("name被改成了", val)
                }
            })
            data.name = 'sh'
            */

            //正确写法
            let obs = new Observer(data)
            console.log(obs)

            //模拟一个vm
            let vm = {}
            vm._data = data = obs

            //创建一个监视的实例对象，用于监视data中所有属性改变
            function Observer(obj) {
                //获取所有key构成的数组
                let keys = Object.keys(obj)
                //为Observer添加data的每个key的数据代理
                keys.forEach(key=>{
                    Object.defineProperty(this, key, {
                        get() {
                            return obj[key] //key是个变量，不能用obj.key，用obj[key]
                        },
                        set(val) {
                            obj[key] = val
                            console.log(`${key}被修改为了${val}，我要去解析模板，生成虚拟DOM...`)
                        }
                    })
                })
            }

            //修改data
            vm._data.address = 'sh'

            //PS
            //Vue中数据监测更完善
            //1：对_data做了数据代理，操作vm.name等价于操作vm._data.name
            //2：对_data中的对象无论嵌套多少层，都会进行数据监测
        
    </script>
</body>
</html>